#ifndef SYSYF_COMSUBEXPRELI_H
#define SYSYF_COMSUBEXPRELI_H

#include "Pass.h"
#include <map>
#include <set>
#include "Instruction.h"
#include<string>



/*****************************CommonSubExprElimination**************************************/
/***************************This class is based on SSA form*********************************/
/***************************you need to finish this class***********************************/
class ComSubExprEli : public Pass {
public:
    explicit ComSubExprEli(Module* module):Pass(module){}
    bool is_valid_expr(Instruction *inst);

    const std::string get_name() const override {return name;}
    void execute() override;
    //static bool is_valid_expr(Instruction* inst);
    void ExprCount(BasicBlock* BB);
    void ComSubExprBFS(Function* func);
    void ComSubExprOpt(Function* func);
    void phiOpt(Function* func);
    void DeleteInst(Function* func);
    bool is_cal_expr(Instruction* inst);
    bool is_equal(Instruction* inst1, Instruction* inst2);
    void addrToString(Instruction* inst,std::string& s){
        auto const_inst1=dynamic_cast<ConstantInt*>(inst->get_operand(0));
        auto const_inst2=dynamic_cast<ConstantInt*>(inst->get_operand(1));
        long addr1,addr2;
        if(const_inst1)
            addr1=const_inst1->get_value();
        else 
            addr1=(long)inst->get_operand(0);
        if(const_inst2)
            addr2=const_inst2->get_value();
        else 
            addr2=(long)inst->get_operand(0);
        std::string s2=inst->get_instr_op_name();
        std::string s1=std::to_string(addr1);
        std::string s3=std::to_string(addr2);
        s.append(s1);
        s.append(s2);
        s.append(s3);
    }
    void local_opt(Function* func);
    void global_count(Function* func);//统计in和out
    void global_opt(Function* func);
private:
    const std::string name = "ComSubExprEli";
};

#endif // SYSYF_COMSUBEXPRELI_H